package cn.fanyamin.business.job;

import java.sql.Timestamp;
import java.util.List;

import javax.mail.MessagingException;

import org.apache.commons.lang.StringUtils;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;


import cn.fanyamin.business.NoResultsFoundException;
import cn.fanyamin.dao.BookDao;
import cn.fanyamin.dao.TaskDao;
import cn.fanyamin.dao.UserDao;
import cn.fanyamin.domain.BookSearchCriteria;
import cn.fanyamin.domain.EmailTask;
import cn.fanyamin.domain.Remind;
import cn.fanyamin.domain.RemindTask;
import cn.fanyamin.domain.RepeatInfo;
import cn.fanyamin.domain.Task;
import cn.fanyamin.domain.User;
import cn.fanyamin.util.collection.CollectionUtils;
import cn.fanyamin.util.email.Email;
import cn.fanyamin.util.email.EmailSender;
import cn.fanyamin.util.net.SocketUtils;
import cn.fanyamin.web.vo.BookVO;


public class JobServiceImpl implements JobService {
    private static Log logger = LogFactory.getLog(JobServiceImpl.class);
    
	private EmailSender sender = null;
	   
    private TaskDao taskDao;
    
    private UserDao userDao;
    
    private BookDao bookDao;
    
    private int maxDuration;
    
    private String adminEmail;
    
    public void setAdminEmail(String email) {
    	this.adminEmail = email;
    }
        
    public void setMaxDuration(int duration) {
    	this.maxDuration = duration;
    }
    
	public void setBookDao(BookDao bookDao) {
		this.bookDao = bookDao;
	}

	public void setSender(EmailSender sender) {
		this.sender = sender;
	}

	public void setTaskDao(TaskDao taskDao) {
		this.taskDao = taskDao;
	}

	public void setUserDao(UserDao userDao) {
		this.userDao = userDao;
	}

	public void checkUserStatus() {
		if(logger.isDebugEnabled()) {
			logger.debug("------------ checkUserStatus ---------------");
		}
	}

	public void cleanup() {
		if(logger.isDebugEnabled()) {
			logger.debug("------------ cleanup ---------------");
		}
		int row1 = taskDao.cleanFinishedTask(50);
		int row2 = taskDao.cleanFinishedRemindTask(50);
		int row3 = taskDao.cleanFinishedEmailTask(50);
		
		logger.info(row1 + ", "+ row2 + "," + row3);
	}

	public void doRemindTask() {
		if(logger.isDebugEnabled()) {
			logger.info("------------ doRemindTask ---------------");
		}
		List<RemindTask> taskList = null;
		try {
			taskList = taskDao.getRemindTaskList();
		} catch(NoResultsFoundException e) {
			return;
		}
		for(RemindTask rt: taskList) {
		    int ret = taskDao.updateRemind(rt.getRemind(), 1);
		    if(ret > 0) {
		        User user = userDao.retrieve(rt.getTask().getUserID());
		        EmailTask mail = new EmailTask();
		        mail.setToAddr(user.getEmail());
		        mail.setSubject("Task reminder");
		        mail.setContent(rt.toString());
		        userDao.createEmailTask(mail);
		        taskDao.updateRemind(rt.getRemind(), Remind.REMIND_END);
		    }
		}
	}

	public void doAlertTask() {
		if(logger.isDebugEnabled()) {
			logger.info("------------ doAlertTask ---------------");
		}
		int pageNo = 0;
		int pageSize = 20;
		BookSearchCriteria criteria = new BookSearchCriteria();
		criteria.setDays(maxDuration);
		List<BookVO> list = bookDao.listBook(pageNo, pageSize, criteria);
		for(BookVO vo: list) {
			User user = userDao.retrieve(vo.getBorrowerID());
			EmailTask mail = new EmailTask();
	        mail.setToAddr(user.getEmail());
	        mail.setCcAddr(this.adminEmail);
	        mail.setSubject("Book return reminder");
	        StringBuilder sb = new StringBuilder();
	        sb.append("Hi " + user.getUserName() + "\n<br/><br/>");
	        sb.append("Please return the book " + vo.getBookName() + " ASAP \n<br/><br/>");
	        sb.append("Regards, \n<br/>Book Admin");
	        mail.setContent(sb.toString());
	        userDao.createEmailTask(mail);
		}
		
	}
	
	public void doRepeatTask() {
		if(logger.isDebugEnabled()) {
			logger.info("------------ doRepeatTask ---------------");
		}
        List<Task> taskList = null;
        try {
            taskList = taskDao.getRepeatTaskList();
        } catch(NoResultsFoundException e) {
            logger.error("getRepeatTask: " ,e);
            return;
        }
        
        
        for(Task task: taskList) {
            RepeatInfo ri = taskDao.retrieveRepeatInfo(task.getRepeatID());
            long beginMS = task.getBeginTime().getTime();
            long currentMS = System.currentTimeMillis();
            if(beginMS > currentMS) {
            	continue;
            }
            while(beginMS < currentMS) {
                beginMS = beginMS + ri.getIntervalMS(task.getBeginTime());
            }
            if(task.getEndTime()==null) {
                task.setEndTime(new Timestamp(System.currentTimeMillis()));
                taskDao.update(task);
                logger.info("update: " + task);
            }
            Task newTask = new Task(task);
            newTask.setBeginTime(new Timestamp(beginMS));
            newTask.setEndTime(null);
            taskDao.create(newTask);
            logger.info("create: " + newTask);
        }
        //taskDao.finishRemindTask(taskList);
    }
	
	public void doEmailTask() {
		if(logger.isDebugEnabled()) {
			logger.info("------------ doEmailTask ---------------");
		}
	    String executor = SocketUtils.getLocalhostIP();
	    int count = 10;
	    int timeoutMS = 300000;
	    List<EmailTask> emailTaskList = userDao.getEmailTaskList(EmailTask.EMAIL_START, count, executor);
	    if(CollectionUtils.isEmpty(emailTaskList)) {
	        int row = userDao.fetchEmailTaskList(executor, count, timeoutMS);
	        if(row == 0) {
	            return;
	        }
	    }
	    
	    emailTaskList = userDao.getEmailTaskList(EmailTask.EMAIL_START, count, executor);
	    if(CollectionUtils.isEmpty(emailTaskList)) {
	        return;
	    }
	    
	    for(EmailTask et: emailTaskList) {
	    	if(StringUtils.isBlank(et.getToAddr())
	    			|| StringUtils.isBlank(et.getFromAddr())
	    			|| StringUtils.isBlank(et.getSubject())
	    			|| StringUtils.isBlank(et.getContent())) {
	    		continue;
	    	}
	        try {
                sender.send(new Email(et.getToAddr(),et.getFromAddr(), et.getSubject(), et.getContent()));
                et.setStatus(EmailTask.EMAIL_END);
                //mail.setStartTime(new Timestamp(System.currentTimeMillis()));
                userDao.updateEmailTask(et);
            } catch (MessagingException e) {
                logger.error("send email error",e);
                et.setStatus(EmailTask.EMAIL_FAILED);
                et.setFailedReason(e.getMessage());
                userDao.updateEmailTask(et);
            }
	    }
	}
}
